using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.SmartParts;
using NUnit.Framework;
using Rhino.Mocks;
using SCSFContrib.CompositeUI.WPF.Workspaces;

namespace SCSFContrib.CompositeUI.WPF.UnitTest.Workspaces
{
	[TestFixture]
	public sealed class ContentControlWorkspaceTest : UnitTest
	{
		private ContentControlWorkspace<object, SmartPartInfo> _contentControlWorkspace;

		protected override void SetUpCore()
		{
			base.SetUpCore();
			_contentControlWorkspace = Mocks.PartialMock<ContentControlWorkspace<object, SmartPartInfo>>();
		}

		[Test]
		public void ActiveSmartPart_ShouldDelegateToComposer()
		{
			Assert.IsNull(_contentControlWorkspace.ActiveSmartPart);
			Assert.AreSame(GetWorkspaceComposer().ActiveSmartPart, _contentControlWorkspace.ActiveSmartPart);

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			GetWorkspaceComposer().SetActiveSmartPart("abc");

			Assert.IsNotNull(_contentControlWorkspace.ActiveSmartPart);
			Assert.AreSame(GetWorkspaceComposer().ActiveSmartPart, _contentControlWorkspace.ActiveSmartPart);
		}

		[Test]
		public void SmartParts_ShouldDelegateToComposer()
		{
			Assert.IsEmpty(_contentControlWorkspace.SmartParts);

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			GetWorkspaceComposer().SetActiveSmartPart("abc");

			Assert.IsNotEmpty(_contentControlWorkspace.SmartParts);
			Assert.AreSame("abc", _contentControlWorkspace.SmartParts[0]);
		}

		[Test]
		public void InnerSmartParts_ShouldDelegateToComposer()
		{
			Assert.IsEmpty(GetPrivateMemberValue<IList<object>>(_contentControlWorkspace, "InnerSmartParts") as ICollection);

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			GetWorkspaceComposer().SetActiveSmartPart("abc");

			Assert.IsNotEmpty(GetPrivateMemberValue<IList<object>>(_contentControlWorkspace, "InnerSmartParts") as ICollection);
			Assert.AreSame("abc", GetPrivateMemberValue<IList<object>>(_contentControlWorkspace, "InnerSmartParts")[0]);
		}

		[Test]
		public void Composer_ShouldGetUnderlyingComposer()
		{
			Assert.IsNotNull(GetPrivateMemberValue<Microsoft.Practices.CompositeUI.SmartParts.WorkspaceComposer<object, SmartPartInfo>>(_contentControlWorkspace, "Composer"));
		}

		[Test]
		public void InjectDependencies_ShouldProvideWorkItemToComposer()
		{
			TestableRootWorkItem workItem = new TestableRootWorkItem();
			_contentControlWorkspace.InjectDependencies(workItem);
			Assert.AreSame(workItem, GetPrivateMemberValue<WorkItem>(typeof(Microsoft.Practices.CompositeUI.SmartParts.Workspace<object, SmartPartInfo>), GetWorkspaceComposer(), "workItem"));
		}

		[Test]
		public void Activate_ShouldDelegateToComposerAndInvokeOnActivate()
		{
			_contentControlWorkspace.OnActivate("abc");
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			_contentControlWorkspace.Activate("abc");
		}

		[Test]
		public void ApplySmartPartInfo_ShouldDelegateToComposerAndInvokeOnApplySmartPartInfo()
		{
			SmartPartInfo smartPartInfo = new SmartPartInfo();
			_contentControlWorkspace.OnApplySmartPartInfo("abc", smartPartInfo);
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			_contentControlWorkspace.ApplySmartPartInfo("abc", smartPartInfo);
		}

		[Test]
		public void Close_ShouldDelegateToComposerAndInvokeOnClose()
		{
			_contentControlWorkspace.OnClose("abc");
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			_contentControlWorkspace.Close("abc");
		}

		[Test]
		public void Hide_ShouldDelegateToComposerAndInvokeOnHide()
		{
			_contentControlWorkspace.OnHide("abc");
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			GetWorkspaceComposer().InnerSmartParts.Add("abc");
			_contentControlWorkspace.Hide("abc");
		}

		[Test]
		public void Show_ShouldDelegateToComposerAndInvokeOnShow()
		{
			_contentControlWorkspace.OnShow("abc", null);
			LastCall.IgnoreArguments().Repeat.Once();
			Mocks.ReplayAll();

			_contentControlWorkspace.Show("abc");
		}

		[Test]
		public void Show_SmartPartInfo_ShouldDelegateToComposerAndInvokeOnShow()
		{
			SmartPartInfo smartPartInfo = new SmartPartInfo();
			_contentControlWorkspace.OnShow("abc", smartPartInfo);
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			_contentControlWorkspace.Show("abc", smartPartInfo);
		}

		[Test]
		public void ConvertFrom_ShouldInvokeOnConvertFrom()
		{
			SmartPartInfo smartPartInfo = new SmartPartInfo();
			_contentControlWorkspace = Mocks.DynamicMock<ContentControlWorkspace<object, SmartPartInfo>>();
			InvokePrivateMethod<SmartPartInfo>(_contentControlWorkspace, "OnConvertFrom", smartPartInfo);
			LastCall.Repeat.Once().Return(smartPartInfo);
			Mocks.ReplayAll();

			(_contentControlWorkspace as IComposableWorkspace<object, SmartPartInfo>).ConvertFrom(smartPartInfo);
		}

		[Test]
		public void RaiseSmartPartActivated_ShouldInvokeOnRaiseSmartPartActivated()
		{
			WorkspaceEventArgs e = new WorkspaceEventArgs("abc");
			_contentControlWorkspace = Mocks.DynamicMock<ContentControlWorkspace<object, SmartPartInfo>>();
			InvokePrivateMethod<SmartPartInfo>(_contentControlWorkspace, "OnSmartPartActivated", e);
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			(_contentControlWorkspace as IComposableWorkspace<object, SmartPartInfo>).RaiseSmartPartActivated(e);
		}

		[Test]
		public void RaiseSmartPartClosing_ShouldInvokeOnRaiseSmartPartClosing()
		{
			WorkspaceCancelEventArgs e = new WorkspaceCancelEventArgs("abc");
			_contentControlWorkspace = Mocks.DynamicMock<ContentControlWorkspace<object, SmartPartInfo>>();
			InvokePrivateMethod<SmartPartInfo>(_contentControlWorkspace, "OnSmartPartClosing", e);
			LastCall.Repeat.Once();
			Mocks.ReplayAll();

			(_contentControlWorkspace as IComposableWorkspace<object, SmartPartInfo>).RaiseSmartPartClosing(e);
		}

		[Test]
		public void OnApplySmartPartInfo_ShouldDoNothingByDefault()
		{
			Mocks.ReplayAll();
			_contentControlWorkspace.OnApplySmartPartInfo(null, null);
		}

		[Test]
		public void OnSmartPartActivated_ShouldRaiseSmartPartActivated()
		{
			Mocks.ReplayAll();
			bool raised = false;

			InvokePrivateMethod<object>(_contentControlWorkspace, "OnSmartPartActivated", new WorkspaceEventArgs("abc"));
			Assert.IsFalse(raised);

			_contentControlWorkspace.SmartPartActivated += delegate
			{
				raised = true;
			};

			InvokePrivateMethod<object>(_contentControlWorkspace, "OnSmartPartActivated", new WorkspaceEventArgs("abc"));
			Assert.IsTrue(raised);
		}

		[Test]
		public void OnSmartPartClosing_ShouldRaiseSmartPartClosing()
		{
			Mocks.ReplayAll();
			bool raised = false;

			InvokePrivateMethod<object>(_contentControlWorkspace, "OnSmartPartClosing", new WorkspaceCancelEventArgs("abc"));
			Assert.IsFalse(raised);

			_contentControlWorkspace.SmartPartClosing += delegate
			{
				raised = true;
			};

			InvokePrivateMethod<object>(_contentControlWorkspace, "OnSmartPartClosing", new WorkspaceCancelEventArgs("abc"));
			Assert.IsTrue(raised);
		}

		[Test]
		public void ConvertFrom_ShouldInvokeDefaultConvertBehavior()
		{
			Mocks.ReplayAll();
			SmartPartInfo source = new SmartPartInfo();
			source.Title = "title";
			source.Description = "desc";
			SmartPartInfo copy = (_contentControlWorkspace as IComposableWorkspace<object, SmartPartInfo>).ConvertFrom(source);
			Assert.AreEqual("title", copy.Title);
			Assert.AreEqual("desc", copy.Description);
		}

		#region Support Methods

		private SCSFContrib.CompositeUI.WPF.Workspaces.WorkspaceComposer<object, SmartPartInfo> GetWorkspaceComposer()
		{
			SCSFContrib.CompositeUI.WPF.Workspaces.WorkspaceComposer<object, SmartPartInfo> composer = GetPrivateMemberValue<SCSFContrib.CompositeUI.WPF.Workspaces.WorkspaceComposer<object, SmartPartInfo>>(_contentControlWorkspace, "Composer");
			return composer;
		}

		#endregion
	}
}
